﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LWrap.Entities;
namespace LWrap.Search
{
    public abstract class SearchBase
    {
        public string IndexLocation { get; set; }

        /// <summary>
        /// Accept the boolean condition to perform the search. The connecting operators should be in caps.
        /// For eg. "DocName:Lucene.NET FAQ AND DocContent:Searching OR DocContent:Indexing" 
        /// </summary>
        public string BooleanCondition { get; set; }

        public string DefaultField { get; set; }

        /// <summary>
        /// Assign the value of the field that should be populated once the search finished.
        /// For eg. If the user adds DocName to the list then the search will return the list of File Name
        /// that satisfies the criteria.
        /// </summary>
        public List<string> FieldValueInSearchResult { get; set; }

        public abstract  List<SearchResultList> ExecuteSearch();
        public virtual List<SearchResultList> ExecuteSearch(string booleanCondition) { return null; }
        public virtual List<SearchResultList> ExecuteSearch(string booleanCondition, string indexLocation) { return null; }
        public virtual List<SearchResultList> ExecuteSearch(string booleanCondition, string indexLocation, List<string> fieldValueInSearchResult) { return null; }

        protected List<SearchResultList> GetSearchResult(Lucene.Net.Search.Hits hits)
        {
            List<SearchResultList> searchResultsList = new List<SearchResultList>();
            for (int i = 0; i < hits.Length(); i++)
            {
                Lucene.Net.Documents.Document doc = hits.Doc(i);
                SearchResultList searchResults = new SearchResultList();
                foreach (string field in this.FieldValueInSearchResult)
                {
                    SearchResult result = new SearchResult();
                    result.Field = field;
                    result.FieldValue = doc.Get(field);
                    searchResults.Add(result);
                }
                searchResultsList.Add(searchResults);
            }
            return searchResultsList;
        }

        public virtual bool IsValidSearch()
        {
            if (string.IsNullOrEmpty(IndexLocation) == true)
            {
                throw new NullReferenceException("Index Location should not be empty");
            }

            if (string.IsNullOrEmpty(BooleanCondition) == true)
            {
                throw new NullReferenceException("Boolean condition should not be empty");
            }
            if (FieldValueInSearchResult == null)
            {
                throw new NullReferenceException("FieldValueInSearchResult should not be null");
            }
            else if (FieldValueInSearchResult.Count <= 0)
            {
                throw new Exception("At least one Field should be added to FieldValueInSearchResult");
            }
            return true;
        }
    }
}
